<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>并发编程</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js"></script>
    <!-- 
        并发编程
          100个请求同时并发执行
            
            1     2      3     4     5       前5个并发执行
            6     7      8     9     10 ...  后面的存入任务队列
            并发执行完一个任务，从队列取队头任务执行

 
          要求： 控制每次5个并发，每执行完一个任务，开启下一个任务
          思路:  定义一个队列，向队列依次放入任务， 
                 任务放入队列前检查队列任务个数是否超过阀值，如果队列个数超过，执行列队任务，
                 

        该段代码是一个使用 JavaScript 编写的函数，函数名为 harexsLimit，函数接受一个参数 maxCount。该函数返回一个新的函数 execute。

        execute 函数的作用是执行传入的 asyncFn 函数，并且限制同时执行的任务数量不超过 maxCount。
        execute 函数内部维护了两个变量：activeCount 表示当前激活（正在执行）的任务数量，waitTask 是一个任务队列，存储等待执行的任务。

        create 函数用于创建待执行任务，并且返回一个匿名函数。该匿名函数内部会调用传入的 asyncFn 函数，并且在任务执行完毕后执行 resolve 或 reject 函数，
        并将任务数量 activeCount 减一。同时，在任务执行完毕后，会从任务队列 waitTask 中取出下一个任务并执行。

        execute 函数内部会根据当前激活任务数量 activeCount 和 maxCount 的大小关系，决定是将任务加入任务队列 waitTask 中，还是立即执行该任务。

        最后，函数返回的是 execute 函数，可以用来调用传入的 asyncFn 函数，并且根据 maxCount 限制同时执行的任务数量。
     -->
</head>

<body>
    <script>
        /**
         * 这段代码的作用是实现任务限流，即限制同时执行的任务数量。
         * 当任务数量超过设定的最大数量时，新的任务会进入任务队列中，
         * 待之前的任务执行完毕后再执行。这样可以避免并发任务过多导致系统资源不足。
         */
        const harexsLimit = (maxCount) => {
            let activeCount = 0 // 激活任务数
            let waitTask = [] // 任务队列

            const execute = (asyncFn, ...args) => {
                return new Promise((resolve, reject) => {
                    const task = create(asyncFn, args, resolve, reject)
                    if (activeCount >= maxCount) {
                        waitTask.push(task)
                    } else {
                        task()
                    }
                })
            }
            /**
             * 创建待执行任务
             */
            const create = (asyncFn, args, resolve, reject) => {
                return () => {
                    asyncFn(...args).then(resolve).catch(reject).finally(() => {
                        activeCount--
                        // 每执行完一个任务启动任务任务队列下个任务
                        if (waitTask.length) {
                            waitTask.shift()() //执行任务
                        }
                    })
                    activeCount++
                }
            }
            return execute
        }

        let limitP = harexsLimit(3)

        function sleep(sec) {
            return new Promise((resolve, reject) => {
                console.log('本函数的执行时要等待' + sec + '秒')
                setTimeout(() => {
                    console.log('等待了' + sec + '秒')
                    resolve()
                }, sec * 1000)
            })
        }
        const RequestGoodsList = (url) => {
            return axios({ method: 'get', url })
        }

        // limitP(sleep, 1)
        // limitP(sleep, 1.1)
        // limitP(sleep, 1.2)
        // limitP(sleep, 3)
        // limitP(sleep, 1.3)
        console.log('start');
        console.time('myTimer');
        let list = []
        for (let i = 0; i < 10; i++) {
            let limit = limitP(RequestGoodsList, 'http://43.136.34.132:8088/api/shop')
            list.push(limit)
        }
        Promise.all(list).then(()=>{
            console.timeEnd('myTimer');
        })

    </script>
</body>

</html>